#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>

WiFiClient tcp;
PubSubClient mqtt(tcp);
DHT sensor(D1, DHT11);

int requestId;

void mqtt_callback(const char* topic, byte* payload, unsigned int length)
{
  Serial.println(topic);
  payload[length] = 0;
  Serial.println((char*)payload);
  if (String(topic) == "$baidu/iot/shadow/NodeMCU/delta")
  {
    const size_t capacity = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 70;
    DynamicJsonDocument doc(capacity);
    deserializeJson(doc, payload, length);

    boolean sw = doc["desired"]["switch"];
    Serial.println(sw);

    if (sw)
    {
      Serial.println("LED on");
      digitalWrite(16, LOW);
    }
    else
    {
      Serial.println("LED off");
      digitalWrite(16, HIGH);
    }
    const size_t capacity1 = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(1) + 40;
    DynamicJsonDocument reported_doc(capacity1);
    reported_doc["requestId"] = String(requestId++);
    JsonObject reported = reported_doc.createNestedObject("reported");
    reported["switch"] = (digitalRead(16) == LOW) ? true : false;
    String msg;
    serializeJson(reported_doc, msg);
    mqtt.publish("$baidu/iot/shadow/NodeMCU/update", msg.c_str());
    Serial.println(msg);
  }
}

void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin("LIUYU", "12345678");
  Serial.begin(74880);
  Serial.println();
  pinMode(16, OUTPUT);
  sensor.begin();
  while (!WiFi.isConnected())
  {
    delay(100);
  }
  Serial.println("WiFi is connected");
  mqtt.setServer("m6bn356.mqtt.iot.gz.baidubce.com", 1883);
  mqtt.setCallback(mqtt_callback);
}

int t;


void loop() {
  if (!mqtt.connected())
  {
    Serial.println("connect to MQTT server");
    mqtt.connect("NodeMCU", "m6bn356/NodeMCU", "6s53h6tez3acr6pr");
    mqtt.subscribe("$baidu/iot/shadow/NodeMCU/delta", 1);
  }
  mqtt.loop();
  if (millis() - t > 10000)
  {
    t = millis();
    float temp = sensor.readTemperature();
    float humi = sensor.readHumidity();
    // {
    //    "requestId":"123",
    //    "reported":{
    //       "temp": 20,
    //       "humi": 30,
    //       "switch": true
    //    }
    // }
    const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 40;
    DynamicJsonDocument doc(capacity);
    doc["requestId"] = String(requestId++);
    JsonObject reported = doc.createNestedObject("reported");
    reported["temp"] = temp;
    reported["humi"] = humi;
    reported["switch"] = (digitalRead(16) == LOW) ? true : false;

    String msg;
    serializeJson(doc, msg);
    mqtt.publish("$baidu/iot/shadow/NodeMCU/update", msg.c_str());
    Serial.println(msg);
  }
}
